package com.imis.module.system.bus;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imis.base.annotation.VerificationCaptcha;
import com.imis.base.constant.CacheConstant;
import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.enums.ArgumentResponseEnum;
import com.imis.base.globle.response.BaseResponse;
import com.imis.base.globle.response.CommonResponse;
import com.imis.base.util.ConvertUtils;
import com.imis.module.api.model.ro.UserRegisterDTO;
import com.imis.module.base.BaseBus;
import com.imis.module.system.model.converter.SysUserConverter;
import com.imis.module.system.model.po.SysOrganization;
import com.imis.module.system.model.po.SysRole;
import com.imis.module.system.model.po.SysUser;
import com.imis.module.system.model.ro.*;
import com.imis.module.system.model.vo.SysUserVO;
import com.imis.module.system.service.ISysOrganizationService;
import com.imis.module.system.service.ISysRoleService;
import com.imis.module.system.service.ISysUserOrganizationService;
import com.imis.module.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * SysUserBus<br>
 * 用户相关功能业务处理类
 * </p>
 *
 * @author XinLau
 * @version 1.0
 * @since 2020年04月15日 11:54
 */
@Service
public class SysUserBus extends BaseBus {

    /**
     * 用户信息 服务类
     */
    private ISysUserService sysUserService;

    @Autowired
    public void setSysUserService(ISysUserService sysUserService) {
        this.sysUserService = sysUserService;
    }

    /**
     * 角色信息 服务类
     */
    private ISysRoleService sysRoleService;

    @Autowired
    public void setSysRoleService(ISysRoleService sysRoleService) {
        this.sysRoleService = sysRoleService;
    }

    /**
     * 组织机构 服务类
     */
    private ISysOrganizationService serviceBySysOrganizationService;

    @Autowired
    public void setSysOrganizationService(ISysOrganizationService serviceBySysOrganizationService) {
        this.serviceBySysOrganizationService = serviceBySysOrganizationService;
    }

    /**
     * 用户-组织机构关联表 服务类
     */
    private ISysUserOrganizationService sysUserOrganizationService;

    @Autowired
    public void setSysUserOrganizationService(ISysUserOrganizationService sysUserOrganizationService) {
        this.sysUserOrganizationService = sysUserOrganizationService;
    }

    /**
     * 添加用户校验
     *
     * @param register - 系统用户添加
     * @return SysUser - 系统用户
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/9 9:47
     */
    private SysUser userAddVerification(UserRegisterDTO register) {
        SysUser sysUser = this.sysUserService.queryUserByName(register.getUsername());
        // 判断用户是否存在
        if (ConvertUtils.isNotEmpty(sysUser)) {
            // 情况1：根据用户信息查询，该用户已注销
            ArgumentResponseEnum.USER_ADD_ERR_DELETE.assertIsTrue(CommonConstant.DEL_FLAG_DELETE.equals(sysUser.getDelFlag()), sysUser.getUsername());
            // 情况2：根据用户信息查询，该用户已冻结
            ArgumentResponseEnum.USER_ADD_ERR_FREEZE.assertIsTrue(CommonConstant.USER_FREEZE.equals(sysUser.getStatus()), sysUser.getUsername());
            // 情况3.根据用户信息查询，该用户存在
            ArgumentResponseEnum.USER_ADD_ERR_REPEAT.assertIsNull(sysUser, register.getUsername());
        }
        return SysUserConverter.INSTANCE.getAddEntity(register);
    }

    /**
     * 为用户更新校验
     *
     * @param sysUserUpdate - 用户更新对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:18
     */
    private SysUser userUpdateVerification(SysUserUpdateRO sysUserUpdate) {
        SysUser sysUser = this.sysUserService.getById(sysUserUpdate.getId());
        ArgumentResponseEnum.USER_UPDATE_ERR_NON.assertNotNull(sysUser);
        SysUserConverter.INSTANCE.getUpdateEntity(sysUser, sysUserUpdate);
        return sysUser;
    }

    /**
     * 为用户授权角色校验
     *
     * @param sysGrantUserToRole - 为用户授权角色校验
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:18
     */
    private void grantRolesToUserVerification(SysGrantRolesToUserRO sysGrantUserToRole) {
        // 1.验证用户合法性
        Long userId = sysGrantUserToRole.getUserId();
        SysUser sysUser = this.sysUserService.getById(userId);
        ArgumentResponseEnum.GRANT_ROLES_TO_USER_ERR_NON_USER.assertNotNull(sysUser, userId);
        // 2.验证角色合法性
        List<Long> roleIdList = sysGrantUserToRole.getRoleIdList();
        List<SysRole> roleList = this.sysRoleService.listByIds(roleIdList);
        ArgumentResponseEnum.GRANT_MENU_TO_ROLE_ERR_NON_MENU.assertIsTrue(roleIdList.size() == roleList.size(), userId);
    }

    /**
     * 分页查询用户信息
     *
     * @param pagingQueryUserDTO - 系统用户查询对象
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 15:47
     */
    public CommonResponse<Page<SysUserVO>> pagingQuerySysUserListByParameter(final PagingQueryUserDTO pagingQueryUserDTO) {
        Page<SysUserVO> pagingQueryUser = this.sysUserService.pagingQuerySysUserListByParameter(pagingQueryUserDTO);
        return new CommonResponse<>(pagingQueryUser);
    }

    /**
     * 添加用户
     *
     * @param register - 用户注册对象
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public BaseResponse addUser(final UserRegisterDTO register) {
        // 1、校验用户重复
        SysUser sysUser = this.userAddVerification(register);
        // 2、创建新用户
        boolean saveUser = this.sysUserService.saveUser(sysUser);
        ArgumentResponseEnum.USER_ADD_ERR.assertIsTrue(saveUser, register.getUsername());
        return new CommonResponse<>();
    }

    /**
     * 冻结用户
     *
     * @param identification - 用户唯一标识
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public BaseResponse freezeUserByIdentification(final Long identification) {
        // 1.判断用户是否存在
        SysUser sysUser = this.sysUserService.getById(identification);
        ArgumentResponseEnum.USER_FREEZE_ERR_USER_NULL.assertNotNull(sysUser, identification);
        if (CommonConstant.USER_UNFREEZE.equals(sysUser.getStatus())) {
            // 2. Redis 缓存内取出要冻结账号缓存 Token 的 Key
            String redisTokenKey = (String) this.redisUtil.hget(CacheConstant.PREFIX_SYS_USER_ID_TOKEN, sysUser.getId().toString());
            if (StrUtil.isNotEmpty(redisTokenKey)) {
                // 3.删除用户Token缓存，强制用户下线
                this.redisUtil.del(redisTokenKey);
                // 删除用户Token的Key缓存
                this.redisUtil.del(CacheConstant.PREFIX_SYS_USER_ID_TOKEN, sysUser.getId().toString());
            }
            // 4.修改用户 status - 状态(1：正常  2：冻结 ）
            boolean freeze = this.sysUserService.freezeUserByIdentification(identification);
            ArgumentResponseEnum.USER_FREEZE_ERR.assertIsTrue(freeze, identification);
        }
        return new CommonResponse<>();
    }

    /**
     * 解冻用户
     *
     * @param identification - 用户唯一标识
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public BaseResponse unFreezeUserByIdentification(final Long identification) {
        // 1.判断用户是否存在
        SysUser sysUser = this.sysUserService.getById(identification);
        ArgumentResponseEnum.USER_FREEZE_ERR_USER_NULL.assertNotNull(sysUser, identification);
        // 2.修改用户 status - 状态(1：正常  2：冻结 ）
        boolean unFreeze = this.sysUserService.unFreezeUserByIdentification(identification);
        ArgumentResponseEnum.USER_UNFREEZE_ERR.assertIsTrue(unFreeze, identification);
        return new CommonResponse<>();
    }

    /**
     * 查看用户
     *
     * @param identification - 用户唯一标识
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public CommonResponse<SysUserVO> queryUserById(final Long identification) {
        SysUser sysUser = this.sysUserService.getById(identification);
        return new CommonResponse(SysUserConverter.INSTANCE.getReturnValue(sysUser));
    }

    /**
     * 更新用户信息
     *
     * @param sysUserUpdate - 用户信息
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    public BaseResponse updateById(SysUserUpdateRO sysUserUpdate) {
        // 1.验证信息合法
        SysUser sysUser = this.userUpdateVerification(sysUserUpdate);
        // 2.更新用户信息
        boolean updateById = this.sysUserService.updateById(sysUser);
        ArgumentResponseEnum.USER_UPDATE_ERR.assertIsTrue(updateById, sysUserUpdate.getId());
        // TODO:This 更新用户信息缓存
        return new CommonResponse<>();
    }

    /**
     * 用户授权角色
     *
     * @param sysGrantUserToRole - 用户授权角色
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/19 11:10
     */
    public BaseResponse grantRoleToUser(SysGrantRolesToUserRO sysGrantUserToRole) {
        // 1.为用户授权角色校验
        this.grantRolesToUserVerification(sysGrantUserToRole);
        // 2.授权操作
        boolean grant = this.sysUserService.grantRoleToUser(sysGrantUserToRole);
        ArgumentResponseEnum.GRANT_ROLES_TO_USER_ERR.assertIsTrue(grant, sysGrantUserToRole.getUserId());
        return new CommonResponse<>();
    }

    /**
     * 取消用户角色授权
     *
     * @param userId - 用户编号
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:22
     */
    public BaseResponse terminateAllRoleToUser(final Long userId) {
        // 1.验证用户存在
        SysUser sysUser = this.sysUserService.getById(userId);
        ArgumentResponseEnum.TERMINATE_ALL_ROLE_TO_USER_ERR_NON_USER.assertNotNull(sysUser, userId);
        // 2.撤销授权
        boolean terminate = this.sysUserService.terminateAllRoleToUser(userId);
        ArgumentResponseEnum.TERMINATE_ALL_ROLE_TO_USER_ERR.assertIsTrue(terminate, userId);
        return new CommonResponse<>();
    }

    /**
     * 修改密码
     *
     * @param changePassword - 密码修改对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:25
     */
    @VerificationCaptcha(captcha = "#changePassword.captcha", verificationCodeIdentification = "#changePassword.verificationCodeIdentification")
    public BaseResponse changeUserPassword(SysChangeUserPasswordRO changePassword) {
        // 1.验证用户存在
        Long userId = changePassword.getUserId();
        SysUser sysUser = this.sysUserService.getById(userId);
        ArgumentResponseEnum.CHANGE_USER_PASSWORD_ERR_NON_USER.assertNotNull(sysUser, userId);
        // 2.清除用户 Token，
        String redisTokenKey = (String) this.redisUtil.hget(CacheConstant.PREFIX_SYS_USER_ID_TOKEN, userId.toString());
        if (StrUtil.isNotEmpty(redisTokenKey)) {
            // 删除用户 Token 缓存，强制用户下线
            this.redisUtil.del(redisTokenKey);
            // 删除用户 Token 的 Key 缓存
            this.redisUtil.del(CacheConstant.PREFIX_SYS_USER_ID_TOKEN, userId.toString());
        }
        // 3.修改密码
        boolean change = this.sysUserService.changeUserPassword(sysUser.getUsername(), changePassword.getNewPassword());
        ArgumentResponseEnum.TERMINATE_ALL_ROLE_TO_USER_ERR.assertIsTrue(change, userId);
        return new CommonResponse<>();
    }

    /**
     * 查询组织机构下的用户接口
     *
     * @param pagingQueryUserByOrganizationIdDTO - 根据组织机构查询用户对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public CommonResponse<Page<SysUserVO>> pagingQueryUserByOrganizationIdentification(final PagingQueryUserByOrganizationIdDTO pagingQueryUserByOrganizationIdDTO) {
        SysOrganization sysOrganization = this.serviceBySysOrganizationService.getById(pagingQueryUserByOrganizationIdDTO.getOrganizationId());
        // 1.根据组织机构信息查询，该组织机构不存在
        ArgumentResponseEnum.ORGANIZATION_QUERY_ERR.assertNotNull(sysOrganization);
        Page<SysUserVO> sysUserList = this.sysUserOrganizationService.pagingQueryUserByOrganizationIdentification(pagingQueryUserByOrganizationIdDTO);
        return new CommonResponse<>(sysUserList);
    }

    /**
     * 查询组织机构下没有的用户接口
     *
     * @param pagingQueryUserByOrganizationIdDTO - 根据组织机构查询用户对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/17 14:54
     */
    public CommonResponse<Page<SysUserVO>> pagingQueryUnauthorizedUser(final PagingQueryUserByOrganizationIdDTO pagingQueryUserByOrganizationIdDTO) {
        SysOrganization sysOrganization = this.serviceBySysOrganizationService.getById(pagingQueryUserByOrganizationIdDTO.getOrganizationId());
        // 1.根据组织机构信息查询，该组织机构不存在
        ArgumentResponseEnum.ORGANIZATION_QUERY_ERR.assertNotNull(sysOrganization);
        Page<SysUserVO> sysUserList = this.sysUserOrganizationService.pagingQueryUnauthorizedUser(pagingQueryUserByOrganizationIdDTO);
        return new CommonResponse<>(sysUserList);
    }

}
